﻿/* 
 * Copyright 2010 Justin Pealing
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 *     
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 */

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Web.Hosting;
using Minnow.Web.Http;

namespace Minnow.Web.Asp
{
    public class WebWorkerRequest : SimpleWorkerRequest
    {
        public WebWorkerRequest(IHttpRequest Request, IHttpResponse Response, string FilePath)
            : base (Path.GetFileName(FilePath), Request.Url.Query, new StreamWriter(Response.OutputStream))
        {
            this.Request = Request;
            this.Response = Response;

            this.FilePath = Request.Url.LocalPath;
            this.FilePathTranslated = FilePath;
        }

        public IHttpRequest Request
        {
            get;
            set;
        }

        public IHttpResponse Response
        {
            get;
            set;
        }

        public string AppPath
        {
            get;
            set;
        }

        public string AppPathTranslated
        {
            get;
            set;
        }

        public string FilePath
        {
            get;
            set;
        }

        public string FilePathTranslated
        {
            get;
            set;
        }

        public override string GetAppPath()
        {
            return base.GetAppPath();
        }

        public override string GetAppPathTranslated()
        {
            return base.GetAppPathTranslated();
        }

        public override string GetFilePath()
        {
            return this.FilePath;
        }

        public override string GetFilePathTranslated()
        {
            return this.FilePathTranslated;
        }

        public override string GetHttpVerbName()
        {
            return this.Request.HttpMethod;
        }

        public override string GetHttpVersion()
        {
            return string.Format("HTTP/{0}.{1}", this.Request.ProtocolVersion.Major, this.Request.ProtocolVersion.Minor);
        }

        public override string GetKnownRequestHeader(int index)
        {
            return this.Request.Headers[GetKnownRequestHeaderName(index)];
        }

        public override int GetLocalPort()
        {
            return this.Request.LocalEndPoint.Port;
        }

        public override string GetPathInfo()
        {
            // TODO: Validate this
            string returnValue = this.Request.Url.Query;
            return returnValue;
        }

        public override string GetQueryString()
        {
            string returnValue = this.Request.Url.Query;
            if (returnValue.Length > 0 && returnValue[0] == '?')
            {
                return returnValue.Substring(1);
            }
            return returnValue;
        }

        public override string GetRawUrl()
        {
            return this.Request.RawUrl;
        }

        public override int GetRemotePort()
        {
            return this.Request.RemoteEndPoint.Port;
        }

        public override string GetServerVariable(string name)
        {
            // TODO: Complete this list
            string returnValue;
            switch (name)
            {
                case "HTTPS":
                    returnValue = this.Request.IsSecureConnection ? "on" : "off";
                    break;
                case "HTTP_USER_AGENT":
                    returnValue = this.Request.Headers["UserAgent"];
                    break;
                default:
                    returnValue = null;
                    break;
            }
            return returnValue;
        }

        public override string GetUnknownRequestHeader(string name)
        {
            return this.Request.Headers[name];
        }

        public override string[][] GetUnknownRequestHeaders()
        {
            NameValueCollection headers = this.Request.Headers;

            List<string[]> returnValue = new List<string[]>();
            for (int i = 0; i < headers.Count; i++)
            {
                string headerName = headers.GetKey(i);
                if (GetKnownRequestHeaderIndex(headerName) == -1)
                {
                    returnValue.Add(new string[] { headerName, headers.Get(i)});
                }
            }

            return returnValue.ToArray();
        }

        public override string GetUriPath()
        {
            string returnValue = this.Request.Url.LocalPath;
            return returnValue;
        }

        public override int ReadEntityBody(byte[] buffer, int size)
        {
            return this.Request.InputStream.Read(buffer, 0, size);
        }

        public override int ReadEntityBody(byte[] buffer, int offset, int size)
        {
            return this.Request.InputStream.Read(buffer, offset, size);
        }

        public override void SendKnownResponseHeader(int index, string value)
        {
            this.Response.AppendHeader(GetKnownResponseHeaderName(index), value);
        }

        public override void SendStatus(int statusCode, string statusDescription)
        {
            this.Response.StatusCode = statusCode;
            this.Response.StatusDescription = statusDescription;
        }

        public override void SendUnknownResponseHeader(string name, string value)
        {
            this.Response.AppendHeader(name, value);
        }

        public override void CloseConnection()
        {
            this.Response.Close();
        }

        public override void EndOfRequest()
        {
            this.Response.OutputStream.Close();
        }

        public override void SendResponseFromMemory(byte[] data, int length)
        {
            this.Response.OutputStream.Write(data, 0, length);
        }
    }
}
